package controller

import (
	"context"
	"fmt"
	"github.com/Ullaakut/nmap"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/container/gset"
	"github.com/gogf/gf/v2/frame/g"
	"log"
	"modbuscf/api/v1"
	"modbuscf/internal/bus"
)

var Index = hChat{
	Users: gmap.New(true),
	Names: gset.NewStrSet(true),
}

type hChat struct {
	Users *gmap.Map    // All users in chat.
	Names *gset.StrSet // All names in chat for unique name validation.
}

func (h *hChat) Index(ctx context.Context, req *v1.IndexReq) (res *v1.IndexRes, err error) {
	var (
		r = g.RequestFromCtx(ctx)
	)
	view := r.GetView()
	view.Assign("tplMain", "chat/include/main.html")
	_ = r.Response.WriteTpl("chat/index.html")
	return
}

func (h *hChat) Scan(ctx context.Context, req *v1.ScanReq) (res *v1.ScanRes, err error) {
	//Create a new Nmap scanner instance
	scanner, err := nmap.NewScanner(
		nmap.WithTargets(req.Ip),               // Target your network
		nmap.WithPorts(req.Port),               // Modbus typically uses port 502
		nmap.WithScripts("modbus-discover"),    // Use the Modbus discovery script
		nmap.WithContext(context.Background()), // Use context for timeout and cancel
	)

	if err != nil {
		log.Fatalf("Error creating Nmap scanner: %v", err)
	}

	// Run the Nmap scan
	result, warnings, err := scanner.Run()
	if err != nil {
		log.Fatalf("Error running Nmap scan: %v", err)
	}

	if warnings != nil {
		log.Printf("Warnings: %v", warnings)
	}

	x := ""

	// Process the scan result
	for _, host := range result.Hosts {
		if len(host.Addresses) > 0 {
			for _, port := range host.Ports {
				if port.State.State == "open" {
					x += fmt.Sprintf("%s:%d", host.Addresses[0], port.ID)
				}
			}
		}

	}
	res = &v1.ScanRes{Data: x}
	return
}

func (h *hChat) Test(ctx context.Context, req *v1.TestReq) (res *v1.ScanRes, err error) {
	mod, err := bus.New(req.Ip, req.Port)
	if mod != nil {
		di, err := mod.ReadDI()
		if err != nil {
			return nil, err
		}
		res = &v1.ScanRes{Data: di}
	}
	return
}
func (h *hChat) Edit(ctx context.Context, req *v1.EditReq) (res *v1.ScanRes, err error) {
	mod, err := bus.New(req.Ip, req.Port)
	if mod != nil {
		di, err := mod.EditIp(req.Ip3, "", "")
		if err != nil {
			return nil, err
		}
		res = &v1.ScanRes{Data: di}
	}
	return
}
